#ifndef __BQ76920_H
#define __BQ76920_H

#include "stm32f4xx.h"
#include "i2c1.h"
#include "delay.h"
#include "uart.h"
#include "math.h"
#include "string.h"

/* Register mapping */
#define SYS_STAT  0x00 // Clear bit in this address by writing a '1' to the corresponding bit
#define CELLBAL1  0x01 // for BQ76920
#define CELLBAL2  0x02 // for BQ76930
#define CELLBAL3  0x03 // for BQ76940
#define SYS_CTRL1 0x04 // ADC control and shut down
#define SYS_CTRL2 0x05 // Coulomb counting control and FET control
#define PROTECT1  0x06 // protection setting
#define PROTECT2  0x07 // protection setting
#define PROTECT3  0x08 // protection setting
#define OV_TRIP   0X09 // Over voltage setting
#define UV_TRIP   0x0A // Under voltage setting
#define CC_CFG    0x0B // set to 0x19 during startup
#define VC1_HI    0x0C // voltage cell 1 MSB bit[5-0]
#define VC1_LO    0x0D // voltage cell 1 LSB bit[7-0] 14bit adc
#define VC2_HI    0x0E
#define VC2_LO    0x0F
#define VC3_HI    0x10
#define VC3_LO    0x11
#define VC4_HI    0x12
#define VC4_LO    0x13
#define VC5_HI    0x14
#define VC5_LO    0x15
#define BAT_HI    0x2A // Bat MSB bit[7-0]
#define BAT_LO    0x2B // Bat LSB bit[7-0] 16 bit adc
#define TS1_HI    0x2C // DIETEMP ADC 6 bit MSB [5-0]
#define TS1_LO    0x2D // DIETEMP ADC 8 bit LSB [7-0]
#define CC_HI     0x32 // coulomb counter upper 8 MSB
#define CC_LO     0x33 // coulomb counter lower 8 MSB
#define ADCGAIN1  0x50
#define ADCOFFSET 0x51
#define ADCGAIN2  0x59

// Short circuit in discharge delay
enum SCD_D
{
    SCD_70us_delay  = 0x00, // 70  us
    SCD_100us_delay = 0x01, // 100 us
    SCD_200us_delay = 0x02, // 200 us
    SCD_400us_delay = 0x03  // 400 us
};

// Overcurrent in discharge delay
enum SCD_T
{
    SCD_Threshold_44mV  = 0x00, // (RSNS = '1')
    SCD_Threshold_67mV  = 0x01, // Voltage drop in Sense resistor
    SCD_Threshold_89mV  = 0x02,
    SCD_Threshold_111mV = 0x03,
    SCD_Threshold_133mV = 0x04,
    SCD_Threshold_155mV = 0x05,
    SCD_Threshold_178mV = 0x06,
    SCD_Threshold_200mV = 0x07,
};

// Overcurrent in discharge delay
enum OCD_D
{
    OCD_8ms_delay    = 0x00, // 8	ms
    OCD_20ms_delay   = 0x01, // 20	ms
    OCD_40ms_delay   = 0x02, // 40	ms
    OCD_80ms_delay   = 0x03, // 80 	ms
    OCD_160ms_delay  = 0x04, // 160 	ms
    OCD_320ms_delay  = 0x05, // 320 	ms
    OCD_640ms_delay  = 0x06, // 640 	ms
    OCD_1280ms_delay = 0x07  // 1280	ms
};

// Overcurrent in discharge delay
enum OCD_T
{
    OCD_Threshold_8mV  = 0x00, // (RSNS = '0')
    OCD_Threshold_11mV = 0x01, // Voltage drop in Sense resistor
    OCD_Threshold_14mV = 0x02,
    OCD_Threshold_17mV = 0x03,
    OCD_Threshold_19mV = 0x04,
    OCD_Threshold_22mV = 0x05,
    OCD_Threshold_25mV = 0x06,
    OCD_Threshold_28mV = 0x07,
    OCD_Threshold_31mV = 0x08,
    OCD_Threshold_33mV = 0x09,
    OCD_Threshold_36mV = 0x0A,
    OCD_Threshold_39mV = 0x0B,
    OCD_Threshold_42mV = 0x0C,
    OCD_Threshold_44mV = 0x0D,
    OCD_Threshold_47mV = 0x0E,
    OCD_Threshold_50mV = 0x0F
};

// undervoltage cell delay
enum UV_D
{
    UV_Delay_1s  = 0x00,
    UV_Delay_4s  = 0x01,
    UV_Delay_8s  = 0x02,
    UV_Delay_16s = 0x03
};

// undervoltage cell delay
enum OV_D
{
    OV_Delay_1s = 0x00,
    OV_Delay_2s = 0x01,
    OV_Delay_4s = 0x02,
    OV_Delay_8s = 0x03
};

// cell number
#define BQ76920_CELL_NUM 5

// Ternary lithium battery
#define TLB_OV_PROTECT 4.20 // cell overvoltage protection voltage
#define TLB_OV_RELIEVE 4.18 // cell overvoltage relieve voltage
#define TLB_UV_PROTECT 3.10 // cell undervoltage protection voltage
#define TLB_UV_RELIEVE 3.15 // cell undervoltage relieve voltage

// BQ76920 data structure
typedef struct
{
    uint16_t GAIN;
    int8_t OFFSET;
    uint32_t cellVoltage[BQ76920_CELL_NUM];
    uint32_t packVoltage;
    float current;
    float TsTemp;
    uint8_t chargeState;
    uint8_t dischargeState;
} BQ76920_t;

// TS1 Pin definition
#define BQ76920_TS1_Clk      RCC_AHB1Periph_GPIOB
#define BQ76920_TS1_Port     GPIOB
#define BQ76920_TS1_Pin      GPIO_Pin_6
#define MCU_WAKE_BQ_ONOFF(x) GPIO_WriteBit(BQ76920_TS1_Port, BQ76920_TS1_Pin, x)

// Low-level function
#define BQ76920_ReadRegister         IIC1_read_one_byte
#define BQ76920_WriteRegister        IIC1_write_one_byte
#define BQ76920_WriteRegisterWithCRC IIC1_write_one_byte_CRC

// High-level function
void BQ76920_Init(BQ76920_t *bq_data);
void BQ76920_GetCellVoltage(BQ76920_t *bq_data);
void BQ76920_GetPackVoltage(BQ76920_t *bq_data);
void BQ76920_GetCurrent(BQ76920_t *bq_data);
void BQ76920_GetTsTemp(BQ76920_t *bq_data);
void BQ76920_PrintInfo(BQ76920_t *bq_data);

void BQ76920_TS1_SetOutMode(void);
void BQ76920_Wakeup(void);
void BQ76920_EntryShip(void);
void BQ76920_GetADCGainOffset(BQ76920_t *bq_data);
void BQ76920_OCDAndSCDProtect(void);
void BQ76920_OVAndUVProtect(BQ76920_t *bq_data);
void BQ76920_GetState(BQ76920_t *bq_data);
void BQ76920_OpenCHG(BQ76920_t *bq_data);
void BQ76920_CloseCHG(BQ76920_t *bq_data);
void BQ76920_OpenDSG(BQ76920_t *bq_data);
void BQ76920_CloseDSG(BQ76920_t *bq_data);
void BQ76920_OpenDSGAndCHG(void);
void BQ76920_CloseDSGAndCHG(void);

#endif
